#!/usr/bin/env python
################################################################
# Author:  Abael Heyijun<hyjdyx@gmail.com>
# Date： 2012-03-15
# Version: 1.0
################################################################

from sys import exit
from os import path
from subprocess import check_output, Popen, STDOUT
import sys

################################################################

isabs = path.isabs
isfile = path.isfile
isdir = path.isdir
islink = path.islink
ismount = path.ismount
run = lambda cmd: check_output(cmd, shell=True)

#################################################################

class ApkTest:
    apk = ''
    apkInfo = ''
    pkgName = ''
    actName = ''

    result = {}

    def __init__(self, apk):
        self.apk = apk

    def init(self):

        self.getApkInfo()
        self.result = dict((i[4:], [False, ''])  for i in dir(ApkTest)  if i[0:4] == 'test' and   len(i) > 4 and  i[4].isupper())

    def runTests(self):
        self.init()

        self.testInstall()
        self.testReinstall()
        self.testStartStop()
        self.testUninstall()

        self.summary()



    def getApkInfo(self):
        fmt = lambda key: dict((i.split('=')[0], i.split('=')[1].strip("'"))   for i in key.split()  if i.find('=') != -1)
        try:
            info = dict(j.split(':', 1) for  j in  (i for i in  run('aapt dump   badging %s' % (self.apk)).split('\n')) if j.find(':') != -1)
            self.pkgName = fmt(info['package'])['name']
            self.actName = fmt(info['launchable-activity'])['name']
        except (IOError):
            print 'ERROR: Failed open apk file:' + self.apk
            exit(-1)
        except (RuntimeError, TypeError, NameError):
            print 'ERROR: Failed get apk info:' + self.apk
            exit(-1)

    def testInstall(self):
        run('adb uninstall  %s' % (self.pkgName))
        self.result['Install'][1] = check_output('adb install %s' % (self.apk), shell=True, stderr=STDOUT)
        if self.result['Install'][1][-9:-2] == 'Success':
            self.result['Install'][0] = True

    def testReinstall(self):
        self.result['Reinstall'][1] = check_output('adb install -r %s' % (self.apk), shell=True, stderr=STDOUT)
        if self.result['Reinstall'][1][-9:-2] == 'Success':
            self.result['Reinstall'][0] = True

    def testStartStop(self):
        Popen(['adb', 'shell', 'am', 'kill', self.pkgName]).wait()
        Popen(['adb', 'shell', 'am', 'force-stop', self.pkgName]).wait()
        self.result['StartStop'][1] = run('adb shell am start %s/%s' % (self.pkgName, self.actName))
        if run('adb shell ps').find(' %s\r\n' % (self.pkgName)) >= 0:
            Popen(['adb', 'shell', 'am', 'kill', self.pkgName]).wait()
            Popen(['adb', 'shell', 'am', 'force-stop', self.pkgName]).wait()
            if run('adb shell ps').find(' %s\r\n' % (self.pkgName)) == -1:
                self.result['StartStop'][0] = True

    def testUninstall(self):
        while True:
            try:
                self.result['Uninstall'][1] = run('adb uninstall  %s' % (self.pkgName))
                if self.result['Uninstall'][1][-9:-2] == 'Success':
                    self.result['Uninstall'][0] = True
                break
            except (IOError):
                continue

    def summary(self):
        for i in ((k, self.result[k][1]) for k in self.result if k[0].isupper() and self.result[k][0] != True):
            print 'FAILED:%s %s' % (i[0], i[1])

if __name__ == '__main__':
    kwargs = dict(i.strip('\'"').split('=') for i in sys.argv if i.find('=') > 0)
    if not kwargs.has_key('apk'):
        print 'Usage: main.py   apk=<APK_FILE>'
        exit(-1)
    if not isfile(kwargs['apk']):
        print 'ERROR: apk file does not exist:' + kwargs['apk']
        exit(-1)
    p = ApkTest(kwargs['apk'])
    p.runTests()
